package com.meanbean.studytime.controls;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;

import com.meanbean.studytime.StudyTimeFile;
import com.meanbean.studytime.StudyTimeMain;
import com.meanbean.studytime.StudyTimeStage;

import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;

/**
 * Controller for the StudyTimeMenuBar.fxml.
 * @author Derek Webb
 */
public class StudyTimeMenuBar extends AnchorPane
{
	@FXML private Label modeLabel;
	@FXML private MenuItem resetMenuItem;
	
	private StudyTimeStage studyTimeStage;
	
	/**
	 * Creates a StudyTimeMenuBar object.
	 * @param studyTimeStage The stage that is will display this object.
	 */
	public StudyTimeMenuBar(StudyTimeStage studyTimeStage)
	{
		this.studyTimeStage = studyTimeStage;
		
		FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("StudyTimeMenuBar.fxml"));
		fxmlLoader.setRoot(this);
		fxmlLoader.setController(this);
		
		try
		{
			fxmlLoader.load();
			
			modeLabel.setText("Mode: Study");
			
			resetMenuItem.setDisable(false);
		}
		catch (IOException e)
		{
			throw new RuntimeException(e);
		}
	}
	
	public void setModeLabelText(String modeLabelText)
	{
		modeLabel.setText(modeLabelText);
	}
	
	/**
	 * Opens an image (JPG) and creates a new StudyTimeFile object with this image.
	 * Then this will display the StudyTimeFile object on the StudyTimeStage.
	 */
	@FXML
	private void newSTF()
	{
		// If the current STF file needs to be saved
		if (StudyTimeStage.getStudyControl().needsToSaveSTF())
		{
			DialogResult.Result result = askUserToSave();
			
			if (result == DialogResult.Result.Yes)
			{
				try
				{
					StudyTimeStage.getStudyControl().saveSTF();
				}
				catch (Exception e)
				{
					Dialog dialog = new Dialog("Error", "Unable to save the STF file.  Sorry :(");
					dialog.initOwner(studyTimeStage);
					dialog.show();
					
					// TODO: Add log file entry here with the stack trace
					e.printStackTrace();
				}
			}
			else if (result == DialogResult.Result.No)
			{
				// Do not save by doing nothing.  :)
			}
			else if (result == DialogResult.Result.Cancel)
				return;
		}

		Path path = openFileWithType("JPEG");
		
		if (path != null)
		{
			try
			{
				StudyTimeFile studyTimeFile = StudyTimeFile.createWithImageFile(path);
				studyTimeStage.openNewSTF(studyTimeFile);
				
				// Set the program mode
				StudyTimeStage.setMode(StudyTimeStage.Mode.Edit);
			}
			catch (Exception e)
			{
				Dialog dialog = new Dialog("Error", "Unable to open the image file.  Sorry :(");
				dialog.initOwner(studyTimeStage);
				dialog.show();
				
				// TODO: Add log file entry here with the stack trace
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Opens a Study Time File (STF) and creates a new StudyTimeFile object with this STF file.
	 * Then this will display the StudyTimeFile object on the StudyTimeStage.
	 */
	@FXML
	private void openSTF()
	{
		// If the current STF file needs to be saved
		if (StudyTimeStage.getStudyControl().needsToSaveSTF())
		{
			DialogResult.Result result = askUserToSave();
			
			if (result == DialogResult.Result.Yes)
			{
				try
				{
					StudyTimeStage.getStudyControl().saveSTF();
				}
				catch (Exception e)
				{
					Dialog dialog = new Dialog("Error", "Unable to save the STF file.  Sorry :(");
					dialog.initOwner(studyTimeStage);
					dialog.show();
					
					// TODO: Add log file entry here with the stack trace
					e.printStackTrace();
				}
			}
			else if (result == DialogResult.Result.No)
			{
				// Do not save by doing nothing.  :)
			}
			else if (result == DialogResult.Result.Cancel)
				return;
		}
		
		Path path = openFileWithType("STF");
		
		if (path != null)
		{
			try
			{
				StudyTimeFile studyTimeFile = StudyTimeFile.createWithStudyTimeFile(path);
				studyTimeStage.openSTF(studyTimeFile);
				
				// Set the program mode
				StudyTimeStage.setMode(StudyTimeStage.Mode.Study);
			}
			catch (Exception e)
			{
				Dialog dialog = new Dialog("Error", "Unable to open the STF file.  Sorry :(");
				dialog.initOwner(studyTimeStage);
				dialog.show();
				
				// TODO: Add log file entry here with the stack trace
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Tells the StudyTimeStage to set the program mode to Study.
	 */
	@FXML
	private void enterStudyMode()
	{
		// Change to Study mode
		StudyTimeStage.setMode(StudyTimeStage.Mode.Study);
	}
	
	/**
	 * Tells the StudyTimeStage to set the program mode to Edit.
	 */
	@FXML
	private void enterEditMode()
	{
		// Change to Edit mode
		StudyTimeStage.setMode(StudyTimeStage.Mode.Edit);
	}
	
	/**
	 * Closes all of the buttons on the stage.
	 */
	@FXML
	private void reset()
	{
		StudyTimeStage.getStudyControl().reloadButtons();
	}
	
	public void disableResetMenuItem(boolean value)
	{
		resetMenuItem.setDisable(value);
	}
	
	/**
	 * Saves the current StudyTimeFile object as an STF file.
	 */
	@FXML
	private void save()
	{
		try
		{
			StudyTimeStage.getStudyControl().saveSTF();
		}
		catch (Exception e)
		{
			Dialog dialog = new Dialog("Error", "Unable to save the STF file.  Sorry :(");
			dialog.initOwner(studyTimeStage);
			dialog.show();
			
			// TODO: Add log file entry here with the stack trace
			e.printStackTrace();
		}
	}
	
	/**
	 * Saves the current StudyTimeFile object as an STF file with a user specified name.
	 */
	@FXML
	private void saveAs()
	{
		try
		{
			StudyTimeStage.getStudyControl().saveSTFas();
		}
		catch (Exception e)
		{
			Dialog dialog = new Dialog("Error", "Unable to save the STF file.  Sorry :(");
			dialog.initOwner(studyTimeStage);
			dialog.show();
			
			// TODO: Add log file entry here with the stack trace
			e.printStackTrace();
		}
	}
	
	/**
	 * Uses a javafx.stage.FileChooser object to open a java.io.File object.
	 * @param fileType The extension type to allow the user to open (JPEG or STF).
	 * @return The user chosen java.io.File object.
	 */
	private Path openFileWithType(String fileType)
	{
		File file = null;
		
		if (fileType.equals("JPEG"))
		{
			FileChooser fileChooser = new FileChooser();
			fileChooser.setTitle("Begin with a JPG file");
			fileChooser.getExtensionFilters().add(new ExtensionFilter("JPEG", "*.jpg", "*.JPG", "*.jpeg", "*.JPEG"));
			
			file = fileChooser.showOpenDialog(studyTimeStage);
		}
		else if (fileType.equals("STF"))
		{
			FileChooser fileChooser = new FileChooser();
			fileChooser.setTitle("Open a Study Time File (STF)");
			fileChooser.getExtensionFilters().add(new ExtensionFilter("STF", "*.stf"));
			
			file = fileChooser.showOpenDialog(studyTimeStage);
		}
		
		if (file != null)
			return file.toPath();
		else
			return null;
	}
	
	@FXML
	private void about()
	{
		try
		{
			java.awt.Desktop.getDesktop().browse(java.net.URI.create("http://code.google.com/p/study-time/"));
		}
		catch (IOException e)
		{
			Dialog dialog = new Dialog("Error", "Unable to open a browser.");
			dialog.initOwner(studyTimeStage);
			dialog.show();
			
			e.printStackTrace();
			
			// TODO: Add log entry here
		}
	}
	
	@FXML
	private void checkForUpdates()
	{
		try
		{
			java.awt.Desktop.getDesktop().browse(java.net.URI.create("http://code.google.com/p/study-time/downloads/list"));
		}
		catch (IOException e)
		{
			Dialog dialog = new Dialog("Error", "Unable to open a browser.");
			dialog.initOwner(studyTimeStage);
			dialog.show();
			
			e.printStackTrace();
			
			// TODO: Add log entry here
		}
	}
	
	@FXML
	private void changeLog()
	{
		try
		{
			java.awt.Desktop.getDesktop().browse(java.net.URI.create("http://code.google.com/p/study-time/wiki/ChangeLog"));
		}
		catch (IOException e)
		{
			Dialog dialog = new Dialog("Error", "Unable to open a browser.");
			dialog.initOwner(studyTimeStage);
			dialog.show();
			
			e.printStackTrace();
			
			// TODO: Add log entry here
		}
	}
	
	@FXML
	private void visitWebsite()
	{
		try
		{
			java.awt.Desktop.getDesktop().browse(java.net.URI.create("http://derek-webb.blogspot.com/"));
		}
		catch (IOException e)
		{
			Dialog dialog = new Dialog("Error", "Unable to open a browser.");
			dialog.initOwner(studyTimeStage);
			dialog.show();
			
			e.printStackTrace();
			
			// TODO: Add log entry here
		}
	}
	
	@FXML
	private void visitFireworksExtravaganzaWebsite()
	{
		try
		{
			java.awt.Desktop.getDesktop().browse(java.net.URI.create("https://play.google.com/store/apps/details?id=com.meanbean.fireworksextravaganza"));
		}
		catch (IOException e)
		{
			Dialog dialog = new Dialog("Error", "Unable to open a browser.");
			dialog.initOwner(studyTimeStage);
			dialog.show();
			
			e.printStackTrace();
			
			// TODO: Add log entry here
		}
	}
	
	/**
	 * Prompts the user with a dialog asking them if they would like to save their STF.
	 */
	private DialogResult.Result askUserToSave()
	{
		DialogResult dialog = new DialogResult("Save Study Time File?", "Would you like to save your changes?");
		dialog.initOwner(studyTimeStage);
		dialog.showAndWait();
		
		return dialog.getResult();
	}
	
	/**
	 * Exits the application.
	 */
	@FXML
	private void exit()
	{
		if (StudyTimeStage.getMode() == StudyTimeStage.Mode.Edit)
			StudyTimeStage.getStudyControl().saveButtons();
		
		if (StudyTimeStage.getStudyControl().needsToSaveSTF())
		{
			try
			{
				DialogResult dialog = new DialogResult("Save Study Time File?", "Would you like to save your changes?");
				dialog.initOwner(StudyTimeMain.studyTimeStage);
				dialog.showAndWait();
				
				if (dialog.getResult() == DialogResult.Result.Yes)
					StudyTimeStage.getStudyControl().saveSTF();
				else if (dialog.getResult() == DialogResult.Result.Cancel)
					return;
				
			} catch (Exception e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		Platform.exit();
	}
}
